/**
 * Base class for views.
 *
 * A View is always tied to a single DOM element and the reference to the element
 * is preserved, allowing quick access to it.
 */
var View = Class.create({
    /**
     * Override in the subclass if necessary, but always remember to call this
     * parent function as well!
     */
    initialize: function(id) {
        this.id = id;
        this.dom = util.el(id); // Store the view static DOM id defined in index.html

        this.data = {};
        this.snippets = {}; // Snippet class objects for handling the dynamic data (see Snippet.js)
        this.subscribes = []; // Subscribed events from EventManager (see EventManager.js)
        
        this.engine = undefined; // Engine object, defined in registerViews() in Engine.js
        this.activationParams = undefined;
    },

    /**
     * Executed right before render. Override in child class if necessary.
     */
    build: function(params) { },

    /**
     * Renders the view. Calls build and then renders all those snippets which have
     * been attached to DOM. 
     */
    render: function(params) {
        if(!this.id || !this.dom) {
            util.log("{View.render} the View is not initialized! ");
            return;
        }

        this.build(params);

        for(var snip in this.snippets) {
            snip = this.snippets[snip];
            if(snip.dom) {
                snip.rewrite();
            }
        }
    },

    /**
     * Attach snippets to the main container snippet for redraw.
     *
     * @param {Object} snippets Hash of snippet objects (key = name for the snippet,
     *                          value = the Snippet object).
     */
    registerSnippets: function(snippets) {
        this.snippets = Object.extend(this.snippets || {}, snippets);
    },

    /**
     * @param {Array} subscribes Array of event objects used for delivering messages
     *                           via publish/subscribe. See EventManager.
     */
    registerSubscribes: function(subscribes) {
        this.subscribes = subscribes || [];
    },

	// Used for activating the view
    activate: function(params) {
        this.activationParams = params;
        this.render(params);
		// Subscribe to events
        this.subscribeAll();
    },

	// Used for deactivating the view
    deactivate: function() {
		// Unsubscribe from all events
        this.unsubscribeAll();
    },

    /**
     * subscribe() and unsubscribe() act in local context, and the actual
     * subscription/unsubscription to EventManger happens in (un)subscribeAll()
     * methods.
     */
    subscribe: function(eventName, callback, context) {
        this.subscribes.push({
            eventName: eventName,
            callback: callback,
            context: context
        });
    },

    unsubscribe: function(eventName, callback, context) {
        for(var i = this.subscribes.length - 1; i >= 0; i--) {
            var s = this.subscribes[i];

            if(s.eventName === eventName &&
               s.callback === callback &&
               s.context === context) {
               this.subscribes.splice(i, 1);
            }
        }
    },

    /**
     * subscribeAll() and unsubscribeAll() registrate/unregistrate the local subscribers
     * to the actual EventManager thus enabling the event delivery.
     */
    subscribeAll: function() {
        for(var i = 0; i < this.subscribes.length; i++) {
            var s = this.subscribes[i];
			// More info on event manager, see EventManager.js
            EventManager.subscribe(s.eventName, s.callback, s.context);
        }
    },

    unsubscribeAll: function() {
        for(var i = 0; i < this.subscribes.length; i++) {
            var s = this.subscribes[i];
			// More info on event manager, see EventManager.js
            EventManager.unsubscribe(s.eventName, s.callback, s.context);
        }
    }
});
